//******************************************************************
//******************************************************************
//**********          ANts Peer To Peer Sources        *************
//
// ANts P2P realizes a third generation P2P net. It protects your
// privacy while you are connected and makes you not trackable, hiding
// your identity (ip) and crypting everything you are sending/receiving
// from others.

// Copyright (C) 2004  Roberto Rossi

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

package ants.p2p.gui;

import java.awt.*;
import javax.swing.*;
import java.beans.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.event.*;

import ants.p2p.*;
import ants.p2p.query.*;
import ants.p2p.query.security.*;

import org.apache.log4j.*;

import com.borland.jbcl.layout.*;
import javax.swing.border.*;
import ants.p2p.utils.indexer.BackgroundEngine;

public class HttpAntPanel extends JPanel implements PropertyChangeListener{
  public static String pic = "./backgrounds/bg8.jpg";
  static Logger _logger = Logger.getLogger(HttpAntPanel.class.getName());

  public static String browserPath = "C:\\Programmi\\mozilla\\mozilla.exe";

  Image buffer;
  JScrollPane jScrollPane1 = new JScrollPane();
  JButton jButton2 = new JButton();
  QueryMessage[] currentQueries = new QueryMessage[0];
  GuiAnt container;
  JLabel jLabel2 = new JLabel();

  ArrayList currentResultSet;
  ArrayList currentSupernodeSet = new ArrayList();
  JPanel jPanel1 = new JPanel();
  XYLayout xYLayout2 = new XYLayout();
  XYLayout xYLayout3 = new XYLayout();
  JPanel jPanel2 = new JPanel();
  XYLayout xYLayout4 = new XYLayout();
  FlowLayout flowLayout1 = new FlowLayout(FlowLayout.LEFT);
  Border border1;
  JList jList1 = new JList();

  public HttpAntPanel(GuiAnt container) {
    this.container=container;
    try{
      Toolkit tk = Toolkit.getDefaultToolkit();
      MediaTracker mt = new MediaTracker(this);
      buffer = tk.getImage(pic);
      mt.waitForAll();
    }catch(Exception e){}
    try {
      jbInit();
    }
    catch(Exception ex) {
      _logger.error("",ex);
    }
    currentResultSet = new ArrayList();
  }
  void jbInit() throws Exception {
    border1 = BorderFactory.createEmptyBorder(20,20,20,20);
    this.setLayout(flowLayout1);
    jButton2.setMaximumSize(new Dimension(200, 50));
    jButton2.setMinimumSize(new Dimension(200, 50));
    jButton2.setPreferredSize(new Dimension(200, 50));
    jButton2.setToolTipText("Search for online web sites on ANts");
    //jButton2.setText(ji.JI.i("Refresh Server List"));
    jButton2.setIcon(new LabelIcon(ji.JI.i("Refresh Server List"),DoubleBuffer.getInstance().getButton(16), jButton2));
    jButton2.addActionListener(new HttpAntPanel_jButton2_actionAdapter(this));
    jLabel2.setToolTipText("your last search state");
    jLabel2.setText(ji.JI.i("no last search..."));
    jPanel1.setLayout(xYLayout3);
    jPanel2.setLayout(xYLayout4);
    jScrollPane1.setMaximumSize(new Dimension(32767, 32767));
    jScrollPane1.setMinimumSize(new Dimension(400, 200));
    jScrollPane1.setPreferredSize(new Dimension(400, 200));
    this.addComponentListener(new HttpAntPanel_this_componentAdapter(this));
    jPanel2.setMinimumSize(new Dimension(480, 55));
    jPanel2.setOpaque(false);
    jPanel2.setPreferredSize(new Dimension(480, 55));
    jPanel2.setRequestFocusEnabled(true);
    jPanel1.setMinimumSize(new Dimension(470, 90));
    jPanel1.setOpaque(false);
    jPanel1.setPreferredSize(new Dimension(470, 90));
    this.setAlignmentX((float) 0.5);
    this.setBorder(border1);
    this.setPreferredSize(new Dimension(1410, 250));
    jList1.addMouseListener(new HttpAntPanel_jList1_mouseAdapter(this));
    jList1.setToolTipText("Found active websites, right click for options");
    jList1.setCellRenderer(new HttpServersCellRenderer(this));
    jPanel1.add(jLabel2,     new XYConstraints(0, 10, -1, -1));
    jPanel2.add(jButton2,        new XYConstraints(0, 0, -1, -1));
    this.add(jPanel2, null);
    this.add(jScrollPane1, null);
    jScrollPane1.getViewport().add(jList1, null);
    this.add(jPanel1, null);
  }

  void jButton2_actionPerformed(ActionEvent e) {
    try{
      Thread.currentThread().setPriority(10);
      synchronized(this.currentResultSet){
        this.currentResultSet = new ArrayList();
        this.currentSupernodeSet = new ArrayList(BackgroundEngine.getInstance().getSupernodeList().keySet());
      }
      Component[] tabs = this.container.jTabbedPane1.getComponents();
      for (int x = 0; x < tabs.length; x++) {
        if (tabs[x] == this) {
          this.container.jTabbedPane1.setIconAt(x,new LabelIcon(
                                                 ji.JI.i("Http Tunneling")+" [" +
                                                 this.currentResultSet.size() +
                                                 "]", DoubleBuffer.getInstance().getButton(16), this.container.jTabbedPane1.getComponentAt(x)));
        }
      }
      //Local
      QueryHttpServerItem httpItem = new QueryHttpServerItem(null);
      AsymmetricProvider ap = new AsymmetricProvider(false);
      QueryManager queryManager = new QueryManager(httpItem, this.container.cap.warriorAnt);
      this.currentQueries = new QueryMessage[1];
      this.currentQueries[0] = new QueryMessage(httpItem, ap.getPublicHeader());
      _logger.info("Displaying local http server results: "+queryManager.resultSet.size());
      PropertyChangeEvent pce = new PropertyChangeEvent(this, "httpServerQueryCompleted", this.currentQueries[0],queryManager.resultSet);
      this.propertyChange(pce);
      _logger.info("Ricevuti i server http locali");
      //Remote
      if(this.currentSupernodeSet.size() > 0){
        MessageWrapper[] queryWrappers = this.container.cap.warriorAnt.doSupernodeQuery(httpItem, ap.getPublicHeader(), this.currentSupernodeSet);
        this.currentQueries = new QueryMessage[queryWrappers.length];
        for(int x = 0; x < queryWrappers.length; x++){
          if(queryWrappers[x].getMessage() != null && queryWrappers[x].getMessage() instanceof QueryMessage){
            this.currentQueries[x] = (QueryMessage) queryWrappers[x].getMessage();
          }
        }
      }else{
        QueryMessage qm = new QueryMessage(httpItem, ap.getPublicHeader());
        MessageWrapper queryWrapper = this.container.cap.warriorAnt.sendBroadcastMessage(qm);
        this.currentQueries = new QueryMessage[1];
        if(queryWrapper.getMessage() != null && queryWrapper.getMessage() instanceof QueryMessage){
          this.currentQueries[0] = (QueryMessage) queryWrapper.getMessage();
          this.jLabel2.setText(ji.JI.i("Refreshing servers list..."));
        }else{
          this.jLabel2.setText(ji.JI.i("Refreshing servers list failed! Retry"));
          throw new Exception("Null query Message in MessageWrapper");
        }
      }
    }catch(Exception ex){_logger.error("Errore nella richiesta di esecuzione query",ex);}
  }

  public void propertyChange(PropertyChangeEvent e) {
    if (e.getPropertyName().equals("httpServerQueryCompleted")) {
      if (this.currentQueries.length > 0){
        QueryMessage eventQuerySource = (QueryMessage) e.getOldValue();
        boolean found = false;
        for(int x = 0; x < this.currentQueries.length; x++){
          if(this.currentQueries[x] != null &&
             eventQuerySource.getLocalQueryId() == this.currentQueries[x].getLocalQueryId())
            found = true;
        }
        if(found){
          synchronized(this.currentResultSet){
            this.currentResultSet = this.mergeQueryResults( (ArrayList) e.getNewValue());
            this.jList1.setListData(this.currentResultSet.toArray());
          }
          this.jList1.revalidate();
        }
        this.jLabel2.setText(ji.JI.i("Received ")+this.currentResultSet.size()+" "+ji.JI.i("results.")+" ");
        Component[] tabs = this.container.jTabbedPane1.getComponents();
        for (int x = 0; x < tabs.length; x++) {
          if (tabs[x] == this) {
            this.container.jTabbedPane1.setIconAt(x,new LabelIcon(
                                                 ji.JI.i("Http Tunneling")+" [" +
                                                 this.currentResultSet.size() +
                                                 "]", DoubleBuffer.getInstance().getButton(16), this.container.jTabbedPane1.getComponentAt(x)));
          }
        }
        if(this.container.cap.warriorAnt.getCurrentProxy() != null){
          this.jLabel2.setText(this.jLabel2.getText()+"   "+ji.JI.i("Active Proxy running on port")+": "+this.container.cap.warriorAnt.getCurrentProxy().getPort());
        }
        else {
          this.jLabel2.setText(this.jLabel2.getText() + "   "+ji.JI.i("No active proxy")+"...");
        }
        this.repaint();
      }
    }
    else if (e.getPropertyName().equals("currentProxyChanged")) {
      this.jList1.revalidate();
      this.jLabel2.setText(ji.JI.i("Received ") + this.currentResultSet.size() +
                           " "+ji.JI.i("results.")+" ");
      if (this.container.cap.warriorAnt.getCurrentProxy() != null) {
        this.jLabel2.setText(this.jLabel2.getText() +
                             "   "+ji.JI.i("Active Proxy running on port")+": " +
                             this.container.cap.warriorAnt.getCurrentProxy().
                             getPort());
      }else{
        this.jLabel2.setText(this.jLabel2.getText() + "   "+ji.JI.i("No active proxy")+"...");
      }
      this.repaint();
    }
  }

  public ArrayList mergeQueryResults(ArrayList resultSet){
    ArrayList tupleGroups = this.currentResultSet;
    for(int x=0; x < resultSet.size(); x++){
      if(resultSet.get(x) instanceof HttpServerInfo &&
         !tupleGroups.contains(resultSet.get(x))){
        tupleGroups.add(resultSet.get(x));
      }
    }
    return tupleGroups;
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (buffer != null) {
      int posX = (this.getWidth() - 650) / 2;
      int posY = (this.getHeight() - 550) / 2;
      if(posX < 0) posX = 0;
      if(posY < 0) posY = 0;
      g.drawImage(buffer, posX, posY, this);
    }
  }

  void this_componentResized(ComponentEvent e) {
    this.jPanel1.setPreferredSize(new Dimension(this.getWidth(),this.jPanel1.getHeight()));
    this.jPanel1.setSize(new Dimension(this.getWidth(),this.jPanel1.getHeight()));
    this.jPanel2.setPreferredSize(new Dimension(this.getWidth(),this.jPanel2.getHeight()));
    this.jPanel2.setSize(new Dimension(this.getWidth(),this.jPanel2.getHeight()));
    this.jScrollPane1.setPreferredSize(new Dimension(this.getWidth()-50, this.getHeight() - 300));
    this.jScrollPane1.setSize(new Dimension(this.getWidth()-50, this.getHeight() - 300));
  }

  void jList1_mousePressed(MouseEvent e) {
    if (e.getClickCount() == 1 &&
          (e.getButton() == MouseEvent.BUTTON3 ||
           (e.getButton() == MouseEvent.BUTTON1 && e.isControlDown()))) {
      HttpPopupMenu popup = new HttpPopupMenu(this,
                                              (HttpServerInfo)this.jList1.getSelectedValue());
      popup.show(e.getComponent(), e.getX(), e.getY());
    }
  }

}

class HttpAntPanel_jButton2_actionAdapter implements java.awt.event.ActionListener {
  HttpAntPanel adaptee;

  HttpAntPanel_jButton2_actionAdapter(HttpAntPanel adaptee) {
    this.adaptee = adaptee;
  }
  public void actionPerformed(ActionEvent e) {
    final ActionEvent event = e;
    final SwingWorker worker = new SwingWorker() {
      public Object construct() {
        adaptee.jButton2_actionPerformed(event);
        return null;
      }
    };
    worker.start();
  }
}

class HttpAntPanel_this_componentAdapter extends java.awt.event.ComponentAdapter {
  HttpAntPanel adaptee;

  HttpAntPanel_this_componentAdapter(HttpAntPanel adaptee) {
    this.adaptee = adaptee;
  }
  public void componentResized(ComponentEvent e) {
    adaptee.this_componentResized(e);
  }
}

class HttpServersCellRenderer extends JLabel implements ListCellRenderer {
     HttpAntPanel hap;

     public HttpServersCellRenderer(HttpAntPanel hap) {
         this.hap = hap;
         setOpaque(true);
     }
     public Component getListCellRendererComponent(
         JList list,
         Object value,
         int index,
         boolean isSelected,
         boolean cellHasFocus)
     {
         setText(value.toString());
         boolean isActive;
         if(hap.container.cap.warriorAnt.getCurrentProxy() == null)
           isActive = false;
         else if(((HttpServerInfo)value).getOwnerId().equals(hap.container.cap.warriorAnt.getCurrentProxy().getNodeID()))
           isActive = true;
         else
           isActive = false;
         if(!isActive){
           setBackground(isSelected ? Color.blue : Color.white);
           setForeground(isSelected ? Color.white : Color.black);
         }else{
           setBackground(Color.lightGray);
           setForeground(Color.black);
         }
         this.setFont(new java.awt.Font("Monospaced", 0, 11));
         return this;
     }
 }

class HttpAntPanel_jList1_mouseAdapter extends java.awt.event.MouseAdapter {
  HttpAntPanel adaptee;

  HttpAntPanel_jList1_mouseAdapter(HttpAntPanel adaptee) {
    this.adaptee = adaptee;
  }
  public void mousePressed(MouseEvent e) {
    adaptee.jList1_mousePressed(e);
  }
}

